const fog_frag =/*wgsl*/`
struct Input {  
    @location(0) uv : vec2<f32>,
    @location(1) fragPosition : vec2<f32>,
};
struct Output {
    @location(0) color:vec4<f32>,
};
struct DepthFog{
    fogType:f32,//0线性雾 1指数雾 2指数平方雾
    density:f32,//雾强度
    start:f32,//雾开始
    end:f32,//雾结束距离
    color:vec3<f32>,//雾颜色
    atten:f32//雾的衰减
}
struct HeightFog{
    fogType:f32,//0线性雾 1指数雾 2指数平方雾
    density:f32,//雾强度
    start:f32,//雾开始
    end:f32,//雾结束距离
    color:vec3<f32>,//雾颜色
    distance:f32//起雾距离
}
fn viewZToOrthographicDepth(viewZ:f32,near:f32,far:f32)->f32 {
	return ( viewZ + near ) / ( near - far );
}
fn orthographicDepthToViewZ(linearClipZ:f32,near:f32,far:f32 )->f32 {
	return linearClipZ * ( near - far ) - near;
}

fn viewZToPerspectiveDepth(viewZ:f32,near:f32,far:f32 )->f32 {
	return ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );
}
fn perspectiveDepthToViewZ(invClipZ:f32,near:f32,far:f32)->f32 {
	return ( near * far ) / ( ( far - near ) * invClipZ - far );
}
fn getDepth(screenPosition:vec2<f32>)->f32 {
    return textureSample(TextureDepth, Sampler,screenPosition);//[0-1]
}

fn getLinearDepth(screenPosition:vec2<f32>)->f32 {
    var fragCoordZ:f32 = getDepth(screenPosition);
    var viewZ:f32 = perspectiveDepthToViewZ( fragCoordZ, camera.near, camera.far);
    return viewZToOrthographicDepth( viewZ,camera.near, camera.far);
}

fn getViewZ(depth:f32)->f32 {
    return perspectiveDepthToViewZ( depth, camera.near, camera.far );
}
fn worldPosition( screenPosition:vec2<f32>, depth:f32)->vec3<f32> {

    //var clipW:f32 = camera.vp[2][3] * viewZ + camera.vp[3][3];

    var worldPos:vec4<f32> = vec4(screenPosition,depth, 1.0 );

    //worldPos *= clipW; // unprojection.
    worldPos=camera.vpInvert * worldPos;
    return worldPos.xyz/worldPos.w;

}
struct Camera{
    vp:mat4x4<f32>,
    vpInvert:mat4x4<f32>,
    view:mat4x4<f32>,
    project:mat4x4<f32>,
    rotation:mat4x4<f32>,
    invert:mat4x4<f32>,
    position:vec3<f32>,
    dist:f32,
    viewport:vec2<f32>,
    near:f32,
    far:f32,
    at:vec3<f32>
  }
@group(0) @binding(0) var Sampler: sampler;
@group(0) @binding(1) var Texture: texture_2d<f32>;
@group(0) @binding(2) var TextureDepth: texture_depth_2d;
@group(0) @binding(3) var<uniform> camera : Camera;
@group(0) @binding(4) var<uniform> depthfog:DepthFog;
@group(0) @binding(5) var<uniform> heightfog:HeightFog;
@fragment
fn main(input:Input) -> Output {
    var output:Output;
    var depth:f32=getDepth(input.uv);//[0-1]
    //var viewZ:f32=getViewZ(depth);//视图空间的深度值
    var worldpos:vec3<f32>=worldPosition(input.fragPosition,depth);//世界坐标值
    var dist:f32=distance(camera.position,worldpos)/depthfog.atten;
    var viewDis=dist/depthfog.atten;
    //计算世界坐标位置
    //根据世界坐标z添加高度雾（在临界值下和陆地颜色混合，临界值以上和天空颜色混合）
    //根据与相机距离计算深度雾
    //混合高度雾和深度雾
    var color:vec4<f32>=textureSample(Texture, Sampler,input.uv);
    var merge:vec3<f32>=color.xyz;
    if(depth==1.0){

    }else{
        //高度雾
        if((distance(camera.at,worldpos))>heightfog.distance){
            var heightFactor:f32=1.0;
            if(heightfog.fogType==1.0){//线性雾
                //fogFactor=saturate((fog.end-viewDis)/(fog.end-fog.start));
                heightFactor=smoothstep(heightfog.start,heightfog.end,worldpos.z);
            }else if(heightfog.fogType==2.0){//指数雾
                heightFactor=1.0-saturate(exp(-heightfog.density*worldpos.z));
            }else if(heightfog.fogType==3.0){//指数平方雾
                heightFactor=1.0-saturate(exp2(-heightfog.density * heightfog.density * worldpos.z * worldpos.z));
            }
            merge=mix(heightfog.color,merge.xyz,heightFactor);
        }
        //深度雾
        var depthFactor:f32=1.0;
        if(depthfog.fogType==1.0){//线性雾
            //fogFactor=saturate((fog.end-viewDis)/(fog.end-fog.start));
            depthFactor=1.0-smoothstep(depthfog.start,depthfog.end,viewDis);
        }else if(depthfog.fogType==2.0){//指数雾
            depthFactor=saturate(exp(-depthfog.density*viewDis));
        }else if(depthfog.fogType==3.0){//指数平方雾
            depthFactor=saturate(exp2(-depthfog.density * depthfog.density * viewDis * viewDis));
        }
        merge=mix(depthfog.color,merge,depthFactor);
    }
    output.color=vec4(merge,color.w);
    return output;
}
`
export {fog_frag}